use bcrypt::{verify};
use futures_util::try_join;
use sqlx::PgPool;
use crate::base::response::Pagination;
use crate::base::Config;
use crate::base::errors::AppError;
use crate::base::jwt::{create_jwt, Claims};
use crate::data::dto::auth_dto::{AddRoleRequest, LoginRequest, LoginResponse, RolePageRequest};
use crate::data::model::role::Role;
use crate::repository::role_repository::RoleRepository;
use crate::repository::user_repository::UserRepository;
use crate::service::user_service::UserService;

/// 认证相关服务
///
/// **作者：** 张翔宇
/// **日期：** 2025年7月1日
pub struct RoleService;

/// 用户注册逻辑
///
/// # 参数
/// * `db_pool` - 数据库连接池
/// * `data` - 注册请求体
/// * `base` - 全局配置
///
/// # 返回
/// 注册成功返回 AuthResponse，失败返回 AppError
impl RoleService {
    // pub async fn register(db_pool: &PgPool, base: Data<Config>, data: RegisterRequest) -> Result<AuthResponse, AppError> {
    //     // 检查电话号码是否已经存在
    //     if UserService::user_exists(db_pool, &data.phone).await? {
    //         return Err(AppError::BadRequest("电话号码已经存在".into()));
    //     }

    //     // 哈希密码
    //     let hashed_password = hash(data.password, DEFAULT_COST).map_err(|_| AppError::Internal)?;

    //     // 创建用户，默认角色为 USER
    //     let user = UserService::create_user(
    //         db_pool,
    //         &data.name,
    //         &data.phone,
    //         &hashed_password,
    //         vec!["USER".to_string()]
    //     ).await?;

    //     // 生成 JWT
    //     let claims = Claims::new(user.id, &base.jwt_expiration);
    //     let token = create_jwt(&claims, &base.jwt_secret)
    //         .map_err(|_| AppError::Runtime("JWT密钥未配置".to_string()))?;
        
        
    //     // 返回注册响应
    //     Ok(AuthResponse {
    //         token,
    //         user_id: user.id,
    //         name: user.username,
    //         phone: user.phone,
    //         // roles: user.roles
    //     })
    // }

    pub async fn login(db_pool: &PgPool, config: &Config, data: LoginRequest) -> Result<LoginResponse, AppError> {
        let user = UserRepository::find_by_username(db_pool, &data.username)
            .await?
            .ok_or(AppError::BadRequest("用户名或密码错误".to_string()))?;

        let valid = verify(&data.password, &user.password_hash)
            .map_err(|_| AppError::BadRequest("解析密码出错".to_string()))?;

        if !valid {
            return Err(AppError::BadRequest("用户名或密码错误".to_string()));
        }

        // 查找用户角色
        let roles = RoleRepository::find_auth_code_by_user_id(db_pool, &user.id).await?;

        // 生成jwt
        let claims = Claims::new(user.id, &config.jwt_expiration, roles.clone());
        let token = create_jwt(&claims, &config.jwt_secret)
            .map_err(|_| AppError::Runtime("生成用户令牌失败".to_string()))?;
        // 生成刷新令牌(30天)
        let refresh_token_expiration: i64 = &config.jwt_expiration * 12 * 30;
        let refresh_claims = Claims::new(user.id, &refresh_token_expiration, roles);
        let refresh_token = create_jwt(&refresh_claims, &config.jwt_secret)
            .map_err(|_| AppError::Runtime("创建刷新令牌失败".to_string()))?;

        let user_info_response = UserService::info(db_pool, &user.id)
            .await?;

        Ok(LoginResponse { 
            token, 
            refresh_token,
            user_info: user_info_response
        })
    }

    /// 添加新角色的异步方法
    /// 功能：在数据库中创建新角色，包含事务处理、角色名称与编码唯一性检查
    /// 参数：
    /// - db_pool: 数据库连接池，用于获取数据库连接
    /// - user_id: 操作人ID，记录谁创建了该角色
    /// - data: 添加角色的请求数据，包含角色名称、编码等信息
    /// 返回：成功时返回创建的角色信息，失败时返回对应的错误类型
    pub async fn add(db_pool: &PgPool, user_id: &i64, data: AddRoleRequest) -> Result<Role, AppError> {
        // 开启事务
        let mut tx = db_pool.begin()
            .await
            .map_err(|e| AppError::Runtime(format!("开启事务失败: {}", e)))?;
        
        // 查询角色名称与编码是否存在
        let (name_exsits, code_exsits) = try_join!(
            RoleRepository::name_exsits(db_pool, &data.name),
            RoleRepository::code_exsits(db_pool, &data.code)
        )?;

        if name_exsits {
            return Err(AppError::BadRequest("角色名称已经存在".to_string()));
        }

        if code_exsits {
            return Err(AppError::BadRequest("角色编码已经存在".to_string()));
        }

        let role = RoleRepository::create(&mut tx, user_id, data).await?;

        // 提交事务
        tx.commit()
            .await
            .map_err(|e| AppError::Runtime(format!("创建角色事务提交失败: {}", e)))?;

        Ok(role)
    }

    pub async fn info(db_pool: &PgPool, id: &i64) -> Result<Role, AppError> {
        RoleRepository::find_by_id(db_pool, id)
            .await
    }

    pub async fn page(db_pool: &PgPool, data: RolePageRequest) -> Result<Pagination<Role>, AppError> {
        // 查询角色及总数
        let (roles, total) = try_join!(
            RoleRepository::page(db_pool, data.current, data.size, data.name.as_deref()),
            RoleRepository::total(db_pool, data.name.as_deref())
        )?;

        Ok(Pagination::create(data.size, data.current, Some(total), roles))
    }
}